<!DOCTYPE html>

















































<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

  <meta name="description" content="Javadoc API documentation for Dormancy." />

<link rel="shortcut icon" type="image/x-icon" href="../../../favicon.ico" />
<title>

  IntrospectorUtils


| Dormancy

</title>
<link href="../../../../assets/doclava-developer-docs.css" rel="stylesheet" type="text/css" />
<link href="../../../../assets/customizations.css" rel="stylesheet" type="text/css" />
<script src="../../../../assets/search_autocomplete.js" type="text/javascript"></script>
<script src="../../../../assets/jquery-resizable.min.js" type="text/javascript"></script>
<script src="../../../../assets/doclava-developer-docs.js" type="text/javascript"></script>
<script src="../../../../assets/prettify.js" type="text/javascript"></script>
<script type="text/javascript">
  setToRoot("../../../", "../../../../assets/");
</script>
<script src="../../../../assets/doclava-developer-reference.js" type="text/javascript"></script>
<script src="../../../../assets/navtree_data.js" type="text/javascript"></script>
<script src="../../../../assets/customizations.js" type="text/javascript"></script>
<noscript>
  <style type="text/css">
    html,body{overflow:auto;}
    #body-content{position:relative; top:0;}
    #doc-content{overflow:visible;border-left:3px solid #666;}
    #side-nav{padding:0;}
    #side-nav .toggle-list ul {display:block;}
    #resize-packages-nav{border-bottom:3px solid #666;}
  </style>
</noscript>
</head>

<body class="">

<div id="header">
    <div id="headerLeft">
    
      <span id="masthead-title">Dormancy</span>
    
    </div>
    <div id="headerRight">
      
  <div id="search" >
      <div id="searchForm">
          <form accept-charset="utf-8" class="gsc-search-box" 
                onsubmit="return submit_search()">
            <table class="gsc-search-box" cellpadding="0" cellspacing="0"><tbody>
                <tr>
                  <td class="gsc-input">
                    <input id="search_autocomplete" class="gsc-input" type="text" size="33" autocomplete="off"
                      title="search developer docs" name="q"
                      value="search developer docs"
                      onFocus="search_focus_changed(this, true)"
                      onBlur="search_focus_changed(this, false)"
                      onkeydown="return search_changed(event, true, '../../../')"
                      onkeyup="return search_changed(event, false, '../../../')" />
                  <div id="search_filtered_div" class="no-display">
                      <table id="search_filtered" cellspacing=0>
                      </table>
                  </div>
                  </td>
                  <td class="gsc-search-button">
                    <input type="submit" value="Search" title="search" id="search-button" class="gsc-search-button" />
                  </td>
                  <td class="gsc-clear-button">
                    <div title="clear results" class="gsc-clear-button">&nbsp;</div>
                  </td>
                </tr></tbody>
              </table>
          </form>
      </div><!-- searchForm -->
  </div><!-- search -->
      
    </div>
</div><!-- header -->


  <div class="g-section g-tpl-240" id="body-content">
    <div class="g-unit g-first side-nav-resizable" id="side-nav">
      <div id="swapper">
        <div id="nav-panels">
          <div id="resize-packages-nav">
            <div id="packages-nav">
              <div id="index-links"><nobr>
                <a href="../../../packages.html"  >Package Index</a> | 
                <a href="../../../classes.html" >Class Index</a></nobr>
              </div>
              <ul>
                
    <li class="api apilevel-">
  <a href="../../../at/dormancy/package-summary.html">at.dormancy</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/access/package-summary.html">at.dormancy.access</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/aop/package-summary.html">at.dormancy.aop</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persistence/package-summary.html">at.dormancy.persistence</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/package-summary.html">at.dormancy.persister</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/callback/package-summary.html">at.dormancy.persister.callback</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/filter/package-summary.html">at.dormancy.persister.filter</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/function/package-summary.html">at.dormancy.persister.function</a></li>
    <li class="api apilevel-">
  <a href="../../../at/dormancy/persister/predicate/package-summary.html">at.dormancy.persister.predicate</a></li>
    <li class="selected api apilevel-">
  <a href="../../../at/dormancy/util/package-summary.html">at.dormancy.util</a></li>
              </ul><br/>
            </div> <!-- end packages -->
          </div> <!-- end resize-packages -->
          <div id="classes-nav">
            <ul>
              
              
    <li><h2>Classes</h2>
      <ul>
          <li class="api apilevel-"><a href="../../../at/dormancy/util/AbstractDormancyUtils.html">AbstractDormancyUtils</a>&lt;PU,&nbsp;PC,&nbsp;PMD,&nbsp;PUP&nbsp;extends&nbsp;<a href="../../../at/dormancy/persistence/PersistenceUnitProvider.html">PersistenceUnitProvider</a>&lt;PU,&nbsp;PC,&nbsp;PMD&gt;&gt;</li>
          <li class="api apilevel-"><a href="../../../at/dormancy/util/ClassLookup.html">ClassLookup</a></li>
          <li class="api apilevel-"><a href="../../../at/dormancy/util/DormancyUtils.html">DormancyUtils</a></li>
          <li class="selected api apilevel-"><a href="../../../at/dormancy/util/IntrospectorUtils.html">IntrospectorUtils</a></li>
          <li class="api apilevel-"><a href="../../../at/dormancy/util/JpaProviderUtils.html">JpaProviderUtils</a></li>
      </ul>
    </li>
              
              
              
              
            </ul><br/>
          </div><!-- end classes -->
        </div><!-- end nav-panels -->
        <div id="nav-tree" style="display:none">
          <div id="index-links"><nobr>
            <a href="../../../packages.html"  >Package Index</a> | 
            <a href="../../../classes.html" >Class Index</a></nobr>
          </div>
        </div><!-- end nav-tree -->
      </div><!-- end swapper -->
    </div> <!-- end side-nav -->
    <script>
      if (!isMobile) {
        $("<a href='#' id='nav-swap' onclick='swapNav();return false;' style='font-size:10px;line-height:9px;margin-left:1em;text-decoration:none;'><span id='tree-link'>Use Tree Navigation</span><span id='panel-link' style='display:none'>Use Panel Navigation</span></a>").appendTo("#side-nav");
        chooseDefaultNav();
        if ($("#nav-tree").is(':visible')) {
          init_default_navtree("../../../");
        } else {
          addLoadEvent(function() {
            scrollIntoView("packages-nav");
            scrollIntoView("classes-nav");
          });
        }
        $("#swapper").css({borderBottom:"2px solid #aaa"});
      } else {
        swapNav(); // tree view should be used on mobile
      }
    </script>



<div class="g-unit" id="doc-content">

<div id="api-info-block">



  
   
  
  
  
  


<div class="sum-details-links">

<div>
<a href="IntrospectorUtils.html">View Documentation</a>
</div>


</div><!-- end sum-details-links -->
<div class="api-level">
  


  
  

</div>
</div><!-- end api-info-block -->


<!-- ======== START OF CLASS DATA ======== -->

<div id="jd-header">
    public
     
     
    
    class
<h1>IntrospectorUtils</h1>



  
    extends <a href="http://download.oracle.com/javase/6/docs/api/index.html?java/lang/Object.html">Object</a><br/>
  
  
  

  
  
  


</div><!-- end header -->
<div id="jd-content">
  <pre class="prettyprint">
/*
 * Copyright 2013 Gregor Schauer
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package at.dormancy.util;

import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.ReflectionUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;

/**
 * Utility class that simplifies bean introspection and caches {@link PropertyDescriptor}s for improved performance.&lt;/p&gt;
 * &lt;p/&gt;
 * There are some alternative solutions e.g.,
 * &lt;ul&gt;
 * &lt;li&gt;Spring´s {@link org.springframework.beans.CachedIntrospectionResults CachedIntrospectionResults} that is a
 * little bit slower but provides more features. Note that it is NOT intended for direct use by application code.&lt;/li&gt;
 * &lt;li&gt;Apache´s {@link org.apache.commons.beanutils.PropertyUtils PropertyUtils}, which are comparable to
 * {@code CachedIntrospectionResults}&lt;/li&gt;
 * &lt;li&gt;Spring´s {@link org.springframework.beans.ConfigurablePropertyAccessor ConfigurablePropertyAccessor} and
 * {@link org.springframework.beans.BeanWrapper BeanWrapper} do not use {@link PropertyDescriptor}s but also provide a
 * convenient way for accessing bean properties&lt;/li&gt;
 * &lt;/ul&gt;
 *
 * @author Gregor Schauer
 * @since 1.1.0
 */
public class IntrospectorUtils {
	protected static Map&lt;Class&lt;?&gt;, Map&lt;String, PropertyDescriptor&gt;&gt; beanInfoMap
			= new IdentityHashMap&lt;Class&lt;?&gt;, Map&lt;String, PropertyDescriptor&gt;&gt;();

	private IntrospectorUtils() {
	}

	/**
	 * Returns the value of the specified property of the specified bean.
	 *
	 * @param bean         bean whose property is to be extracted
	 * @param propertyName propertyName the propertyName of the property to get the value of
	 * @return the value of the property
	 * @see #getFieldValue(Object, String)
	 * @see java.beans.PropertyDescriptor#getReadMethod()
	 */
	@Nullable
	public static Object getValue(@Nonnull Object bean, @Nonnull String propertyName) {
		PropertyDescriptor descriptor = getDescriptorMap(bean.getClass()).get(propertyName);
		Method readMethod = descriptor != null ? descriptor.getReadMethod() : null;
		if (readMethod != null) {
			return ReflectionUtils.invokeMethod(readMethod, bean);
		} else {
			return getFieldValue(bean, propertyName);
		}
	}

	/**
	 * Returns the value of the specified property of the specified bean by accessing it directly.
	 *
	 * @param bean         bean whose property is to be extracted
	 * @param propertyName the propertyName of the property to get the value of
	 * @return the value of the property
	 * @see ReflectionTestUtils#getField(Object, String)
	 */
	@Nonnull
	protected static Object getFieldValue(@Nonnull Object bean, @Nonnull String propertyName) {
		return ReflectionTestUtils.getField(bean, propertyName);
	}

	/**
	 * Sets the value of the specified property of the specified bean.
	 *
	 * @param bean         bean whose property is to be modified
	 * @param propertyName propertyName of the property to be modified
	 * @param value        value to which this property is to be set
	 * @see #setFieldValue(Object, String, Object)
	 * @see java.beans.PropertyDescriptor#getWriteMethod()
	 */
	public static void setValue(@Nonnull Object bean, @Nonnull String propertyName, @Nullable Object value) {
		PropertyDescriptor descriptor = getDescriptorMap(bean.getClass()).get(propertyName);
		Method writeMethod = descriptor != null ? descriptor.getWriteMethod() : null;
		if (writeMethod != null) {
			ReflectionUtils.invokeMethod(writeMethod, bean, value);
		} else {
			setFieldValue(bean, propertyName, value);
		}
	}

	/**
	 * Sets the value of the specified property of the specified bean.
	 *
	 * @param bean         bean whose property is to be set
	 * @param propertyName the propertyName of the property to set the value of
	 * @param value        the new value
	 * @see ReflectionTestUtils#setField(Object, String, Object)
	 */
	protected static void setFieldValue(@Nonnull Object bean, @Nonnull String propertyName, @Nullable Object value) {
		ReflectionTestUtils.setField(bean, propertyName, value);
	}

	/**
	 * Returns a map containing the property names and their corresponding property descriptors.&lt;p/&gt;
	 * &lt;p/&gt;
	 * Due to the fact that {@link #getClass()} is a valid getter method, the method
	 * {@link java.beans.BeanInfo#getPropertyDescriptors()} returns a property descriptor for {@code class}.
	 * This method does NOT return the property {@code class}.
	 *
	 * @param clazz the class to retrieve its property descriptors
	 * @return the property descriptors of the class
	 * @see #getDescriptors(Class)
	 */
	@Nonnull
	protected static Map&lt;String, PropertyDescriptor&gt; getDescriptorMap(@Nonnull Class&lt;?&gt; clazz) {
		Map&lt;String, PropertyDescriptor&gt; descriptorMap = beanInfoMap.get(clazz);
		if (descriptorMap == null) {
			descriptorMap = new HashMap&lt;String, PropertyDescriptor&gt;();
			beanInfoMap.put(clazz, descriptorMap);

			for (PropertyDescriptor descriptor : getDescriptors(clazz)) {
				if (!"class".equals(descriptor.getName())) {
					descriptorMap.put(descriptor.getName(), descriptor);
				}
			}
		}
		return descriptorMap;
	}

	/**
	 * Returns the property descriptors of the given class.&lt;/p&gt;
	 * &lt;p/&gt;
	 * This is just a convenient method that catches the {@link IntrospectionException} and rethrows it as an unchecked
	 * exception.
	 *
	 * @param clazz the class to retrieve its property descriptors
	 * @return the property descriptors of the class
	 * @see Introspector#getBeanInfo(Class)
	 * @see java.beans.BeanInfo#getPropertyDescriptors()
	 */
	@Nonnull
	private static PropertyDescriptor[] getDescriptors(@Nonnull Class&lt;?&gt; clazz) {
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
			return beanInfo.getPropertyDescriptors();
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}
}

  </pre>
</div>
<div id="footer">
Generated by <a href="http://code.google.com/p/doclava/">Doclava</a>.
</div> <!-- end footer -->

</div> <!-- jd-content -->

</div><!-- end doc-content -->

</div> <!-- end body-content --> 

<script type="text/javascript">
init(); /* initialize doclava-developer-docs.js */
</script>

</body>
</html>
